package com.taichuan.selfcheck.hardware.finger;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import com.taichuan.finger.zaz.TcZazFingerClient;
import com.taichuan.selfcheck.eventbus.ZazFingerInitEvent;
import com.taichuan.selfcheck.hardware.DeviceUtils;
import com.taichuan.tcutils.taichuan.PrintUtils;
import org.greenrobot.eventbus.EventBus;
import java.util.concurrent.ConcurrentHashMap;
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * 该类主要用于
 *
 * @author CamelLuo
 * @version 2020/7/1
 */
public class FingerControlClient {
    private static final String TAG = FingerControlClient.class.getSimpleName();

    /**
     * 定义一个变量用于表示 指纹模块初始化失败后重试的最大次数
     */
    private static final int INIT_FINGER_FAILURE_RETRY_MAX_COUNT = 10;
    /**
     * 定义一个变量用于表示 指纹模块初始化失败后重试的间隔时间
     */
    private static final int INIT_FINGER_FAILURE_RETRY_DELAY_TIME = 5 * 1000;

    /**
     * 定义一个Handler 事件 用于在指纹模块初始化失败后 间隔 指定时间 执行指纹模块的重置工作
     */
    private static final int MSG_RESET_FINGER_AND_RETRY_INIT = 1;

    /**
     * 定义一个集合用于存储外部组件注册的FingerInitedListener监听对象
     */
    protected ConcurrentHashMap<String, FingerInitedListener> mFingerInitedListeners = new ConcurrentHashMap<>();



    private HandlerThread handlerThread = null;
    private Handler handler = null;

    /**
     * 定义一个变量用于表示是否正处于重置状态
     */
    private boolean isInResetState = false;

    private int currentResetCount = 0;

    private Context context;

    private FingerInitStateListener stateListener;

    /**
     * 定义一个变量用于表示指纹模块 是否初始化成功
     */
    private boolean isRealInit = false;

    private FingerControlClient() {

    }

    private static class SingletonHolder{
        private final static FingerControlClient instance = new FingerControlClient();
    }

    public static FingerControlClient getInstance() {
        return SingletonHolder.instance;
    }

    public void init(Context context){
        this.context = context;
    }

    public boolean isRealInit() {
        return isRealInit;
    }

    public void setRealInit(boolean realInit) {
        isRealInit = realInit;
    }

    public void initTcZazFingerClient(boolean isFristInit){
        Observable.just("")
                .observeOn(Schedulers.io())
                .map(new Function<String, Boolean>() {
                    @Override
                    public Boolean apply(String s) throws Exception {
                        TcZazFingerClient.getInstance().init(context);

                        //通知外部组件初始化状态
                        refreshInitState(false,"开始初始化指纹模块SDK");

                        //首次初始化指纹模块时才需要执行的流程，
                        if (isFristInit){
                            //休眠3秒再启动流程
                            Thread.sleep(3000);
                            //先注销一次
                            TcZazFingerClient.getInstance().closeFingerSdk();
                            Log.e(TAG, "initTcZazFingerClient: 初始化指纹模块SDK前，先执行一次注销流程");
                            //休眠3秒再启动流程Thread.sleep(3000);
                        }

                        //执行指纹模块初始化流程
                        boolean isSucess = TcZazFingerClient.getInstance().openFingerByUSB();
                        Log.e(TAG, "initTcZazFingerClient: 初始化指纹模块SDK----------------------");
                        if (isSucess){
                            //初始化成功，重置 重置次数计数
                            currentResetCount = 0;
                            //移除Handler事件
                            if (handler != null){
                                handler.removeMessages(MSG_RESET_FINGER_AND_RETRY_INIT);
                            }

                            //休眠1秒
                            Thread.sleep(1000);

                            //通知外部组件初始化状态
                            refreshInitState(true,"初始化指纹模块SDK【成功】");
                        }
                        return isSucess;
                    }
                }).observeOn(Schedulers.io())
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean initResult) throws Exception {
                        Log.e(TAG, "指纹模块初始化结果： " + initResult);

                        for (FingerInitedListener listener : mFingerInitedListeners.values()) {
                            listener.onFingerInited(initResult);
                        }

                        isRealInit = initResult;
                        //将初始化结果发送给外部组件
                        EventBus.getDefault().post(new ZazFingerInitEvent(initResult));
                        if (!initResult){
                            //初始化失败，如果当前设备的初始化失败重试次数未到达上限，则延时指定时间后重置指纹模块
                            //进行日志记录
                            logAndPrint("指纹模块初始化失败，当前的 重试次数为：" + currentResetCount);

                            if (currentResetCount < INIT_FINGER_FAILURE_RETRY_MAX_COUNT){
                                //通知外部组件初始化状态
                                refreshInitState(false,"初始化指纹模块SDK【失败】，" + INIT_FINGER_FAILURE_RETRY_DELAY_TIME
                                               + " 毫秒后进行第" + currentResetCount + "次重试，请耐心等待");

                                //初始化HandlerThread及Handler用于间隔执行重置操作
                                initHandler();
                                //延时 INIT_FINGER_FAILURE_RETRY_DELAY_TIME 时间后 开始重置
                                if (handler != null){
                                    handler.sendEmptyMessageDelayed(MSG_RESET_FINGER_AND_RETRY_INIT,
                                            INIT_FINGER_FAILURE_RETRY_DELAY_TIME);
                                    logAndPrint("指纹模块初始化失败，开始执行重试机制，" + INIT_FINGER_FAILURE_RETRY_DELAY_TIME +
                                            " ms后开始执行");
                                }else {
                                    logAndPrint("指纹模块初始化失败，执行重试异常：Handler实例对象为null");
                                }
                            }else {
                                logAndPrint("指纹模块初始化失败，【重试已到达上限：" + currentResetCount +
                                        " 】，不再尝试重置指纹模块");
                                //通知外部组件初始化状态
                                refreshInitState(true,"初始化指纹模块SDK【失败】,超出重试次数限制，请检查【设备硬件】！");
                            }
                        }

                    }
                });

    }

    public void queryAllFingerAndStartIdentifyThread(){
        Observable.just("")
                .observeOn(Schedulers.io())
                .map(new Function<String, Boolean>() {
                    @Override
                    public Boolean apply(String s) throws Exception {
                        if (isRealInit){
                            //读取指纹模块指纹索引注册状态
                            TcZazFingerClient.getInstance().queryAllFingerIndexRegisterState();
                        }
                        return isRealInit;
                    }
                }).observeOn(Schedulers.io())
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean initResult) throws Exception {
                        TcZazFingerClient.getInstance().startFingerIdentifyThread();
                    }
                });

    }

    /**
     * 定义一个方法用于初始化Handler及HandlerThread，用于处理指纹模块的相关延时操作
     */
    private void initHandler() {
        if (handlerThread == null){
            handlerThread = new HandlerThread("FingerControlClient");
            handlerThread.start();
        }
        if (handler == null){
            handler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    switch (msg.what){
                        case MSG_RESET_FINGER_AND_RETRY_INIT:{
                            //计数+1
                            currentResetCount++;
                            //进行日志记录
                            logAndPrint("接收到 MSG_RESET_FINGER_AND_RETRY_INIT 事件,开始执行指纹模块【重置流程】，计数+1后当前重置次数为： " + currentResetCount);
                            resetTcZazFingerClient("初始化指纹模块失败，尝试重试");

                            //通知外部组件初始化状态
                            refreshInitState(false,"初始化指纹模块SDK【失败】， 【开始执行】指纹模块第" + currentResetCount + "次重试，请耐心等待");
                            break;
                        }
                    }
                    return false;
                }
            });
        }
    }

    /**
     * 定义一个方法用于复位指纹模块
     * @param errorMsg 错误原因
     */
    public void resetTcZazFingerClient(String errorMsg){
        //改变标志位，进入重置状态
        isInResetState = true;
        Observable.just(errorMsg)
                .observeOn(Schedulers.io())
                .map(new Function<String, Boolean>() {

                    @Override
                    public Boolean apply(String msg) throws Exception {
                        //进行日志记录
                        logAndPrint("resetTcZazFingerClient: 指纹模块通信异常，原因为：" + msg + " ,开始执行复位流程：注销指纹模块--------");

                        //注销指纹模块
                        TcZazFingerClient.getInstance().destory(false);

                        //1.5秒后执行指纹模块断电操作
                        Thread.sleep(1500);
                        DeviceUtils.openOrCloseFingerPrint(false);

                        //进行日志记录
                        logAndPrint("resetTcZazFingerClient: 指纹模块通信异常，开始执行复位流程：执行指纹模块【断电】操作--------");

                        //3秒后执行指纹模块上电操作
                        Thread.sleep(1000);
                        DeviceUtils.openOrCloseFingerPrint(true);

                        //进行日志记录
                        logAndPrint("resetTcZazFingerClient: 指纹模块通信异常，开始执行复位流程：执行指纹模块【上电】操作--------");

                        //3秒后尝试再次初始化指纹模块
                        Thread.sleep(1500);
                        initTcZazFingerClient(false);

                        //进行日志记录
                        logAndPrint("resetTcZazFingerClient: 指纹模块通信异常，开始执行复位流程：重新尝试初始化指纹模块-------");
                        //改变标志位，结束重置状态
                        isInResetState = false;
                        return true;
                    }
                }).observeOn(Schedulers.io())
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {

                    }
                });
    }

    public boolean isInResetState() {
        return isInResetState;
    }

    private void logAndPrint(String msg){
        Log.e(TAG, msg);
        PrintUtils.get().print(PrintUtils.LogLevel.FINGER, "FINGER", msg);
    }

    private void refreshInitState(boolean isInitSuccess,String content) {
        if (stateListener != null){
            stateListener.onInitResult(isInitSuccess,content);
        }
    }

    public void setStateListener(FingerInitStateListener stateListener) {
        this.stateListener = stateListener;
    }

    public interface FingerInitedListener {
        /**
         * On Finger inited.
         *
         * @param inited the inited
         */
        void onFingerInited(boolean inited);
    }

    /**
     * 定义一个方法用于让页面组件注册 指纹模块SDK初始化结果事件监听
     * @param tag      标签 建议传入页面类的类名
     * @param listener FingerInitedListener 实例对象
     */
    public void addFingerInitedListener(String tag, FingerInitedListener listener) {
        if (mFingerInitedListeners != null) {
            mFingerInitedListeners.put(tag, listener);
        }
    }

}
